# encoding: utf-8
__author__ = 'user'


class Student(object):  #  object 代表继承的基类

    #属性器
    def get_store(self):
        return self.__store

    def set_store(self, store):
        self.__store = store
    # 构造函数
    # 类中的函数第一个变量必须为self
    def __init__(self, name, store):
        self.__name = name
        self.__store = store  # 属性名称以双下划线开头，则外部类不能访问内部属性

    def show_store(self):
        print "%s's store is %d" % (self.__name, self.__store)

    def grade(self):
        if self.__store >= 90:
            return "A"
        elif self.__store >= 80:
            return "B"
        else:
            return "Err"

will = Student('will', 59)
will.show_store()
print will.get_store()
print will.grade()
print will.set_store(90)
print will.grade()
print will._Student__name #  双下划线实现的内部变量实际上是将变量改名了 一种情况是改为 _+类名+变量名

# 继承与多态
class Animal(object):
    def run(self):
        print "keep running"

    def eating(self):
        print "eating!"

class Dog(Animal):
    age = 0
    # 重载
    def eating(self):
        print "bone"


doggie = Dog()
doggie.run()
doggie.eating()

print isinstance(doggie,Dog) #判断类型
print type(doggie)
import types
print types.TypeType == type(Dog)

print type('北京')

def set_age(self,age):
    self.age = age

from types import MethodType
# 向对象添加方法
sDog = Dog()
sDog.set_age = MethodType(set_age,sDog,Dog)
sDog.set_age(27)
print sDog.age

Dog.set_age = MethodType(set_age,None,Dog)
aDog = Dog()
aDog.set_age(30)
print( aDog.age)

# 限制class属性绑定 当前版本2.7.9无效，只有将这些变量进行向上抽取的功能
class StrictDog(Dog):
    __slots__ = ('eat_meat', 'swim')

s2Dog = StrictDog()
s2Dog.eat_meat = True
s2Dog.swim = True
s2Dog.fight = "wang"
print( s2Dog.__dict__)
print( s2Dog.fight)

# property 装饰器

class Student(object):

    @property
    def store(self):
        return self.__store

    @store.setter
    def store(self,value):
        if not isinstance(value,int):
            raise ValueError ("score must be an int")
        if value<0 or value>100:
            raise ValueError("score must between 0-100 ")
        self.__store = value

    @property
    def grade_s(self):
        return self.__store == 100

sd = Student()
sd.store = 50
print sd.grade_s

# 多重继承 MIXIN 注意处理多重继承带来的基类同名方法问题
# class A(BMixIn,CMixIn)

# 定制类
class Printer(object):
    #类似于toString()
    def __str__(self):
        return  "this is a printer"

    #调试者的toString
    #__repr__ = __str__
print(Printer())
pObject = Printer()


# 迭代器 索引器
class Reader(object):

    def __init__(self):
        self.__base_array = range(10)
        self.__number = -1

    def __iter__(self):
        return self

    def next(self):
        if len(self.__base_array)-1 <=self.__number:
            raise StopIteration()
        else:
            self.__number += 1
            return self.__base_array[self.__number]

    def __getitem__(self, item):
        return self.__base_array[item]

    # 使对象在创建时可调用，提供构造函数返回值？
    def __call__(self, *args, **kwargs):
        pass

for i in Reader():
    print(i)

print ("the index 3 in Reader is :", Reader()[3])

''' 使用type 1动态创建类型 type(string,list(base),dict()) 方法名 继承类 其中存在方法
             2 检测当前类型 type(class)
'''
class BaseClassInIt(object):

    def default_method(self):
        print("abc center")

def ori_fn(self,method_name = "default name"):
    print method_name,"injection"
temp_class = type("Hello",(BaseClassInIt,),dict(first_method = ori_fn))# 实际上 type_class 代指的是
t = temp_class()
t.first_method("method name")
t.default_method()
print type(t)


# meta class 元类 必须派生自type

class ListMetaClass(type):
    def __new__(cls, name, bases, attrs):
        attrs["add"] = lambda self,value : self.append(value)
        return type.__new__(cls, name, bases, attrs)

class MyLists(list):
    __metaclass__ = ListMetaClass

ls = MyLists()
ls.add(1)
print(ls)